class TokenType {
    // type
    static number = new TokenType('number')
    static boolean = new TokenType('boolean')
    static string = new TokenType('string')
    static null = new TokenType('null')
    static variable = new TokenType('variable')

    // keyword: break, const, continue, if, else, while, for
    // function, return, this, var
    static keyword = new TokenType('keyword')

    // operator
    static auto = new TokenType('auto')
    static colon = new TokenType('colon')
    static comma = new TokenType('comma')
    // 分号
    static semicolon = new TokenType('semicolon')

    static equal = new TokenType('equal')
    static assign = new TokenType('assign')

    static notEqual = new TokenType('notEqual')
    static greaterThan = new TokenType('greaterThan')
    static lessThan = new TokenType('lessThan')
    static greaterEqual = new TokenType('greaterEqual')
    static lessEqual = new TokenType('lessEqual')

    static plus = new TokenType('plus')
    static minus = new TokenType('minus')
    static multiply = new TokenType('multiply')
    static divide = new TokenType('divide')

    // += -= *= /= %/
    static assignPlus = new TokenType('assignPlus')
    static assignMinus = new TokenType('assignMinus')
    static assignMultiply = new TokenType('assignMultiply')
    static assignDivide = new TokenType('assignDivide')
    static assignMod = new TokenType('assignMod')

    static and = new TokenType('and')
    static or = new TokenType('or')
    static not = new TokenType('not')

    static mod = new TokenType('mod')
    static dot = new TokenType('dot')

    static bracketLeft = new TokenType('bracketLeft') // [
    static bracketRight = new TokenType('bracketRight') // ]

    static curlyLeft = new TokenType('curlyLeft') // {
    static curlyRight = new TokenType('curlyRight') // }

    static parenthesesLeft = new TokenType('parenthesesLeft') // (
    static parenthesesRight = new TokenType('parenthesesRight') // )

    constructor(name) {
        this.enumName = name
    }

    toString() {
        return `${this.constructor.name}.${this.enumName}`
    }
}

class AstType {
    // expression
    // 对象定义
    static ExpressionObject = new AstType('ExpressionObject')
    // 函数定义
    static ExpressionFunction = new AstType('ExpressionFunction')
    // 数组定义
    static ExpressionArray = new AstType('ExpressionArray')
    // 二元表达式
    static ExpressionBinary = new AstType('ExpressionBinary')
    // 函数调用
    static ExpressionCall = new AstType('ExpressionCall')
    // 赋值
    static ExpressionAssignment = new AstType('ExpressionAssignment')
    // 类的定义
    static ExpressionClass = new AstType('ExpressionClass')
    // 访问(暂时废弃)
    static ExpressionMember = new AstType('ExpressionMember')
    //数组访问 arr[0]
    static ExpressionArrayAccess = new AstType('ExpressionArrayAccess')
    //点访问 this.a this.add(1, 2)
    static ExpressionDotAccess = new AstType('ExpressionDotAccess')


    // statement
    static StatementBlock = new AstType('StatementBlock')
    static StatementIf = new AstType('StatementIf')
    static StatementWhile = new AstType('StatementWhile')
    static StatementFor = new AstType('StatementFor')
    //  返回
    static StatementReturn = new AstType('StatementReturn')

    // 变量声明
    static DeclarationVariable = new AstType('DeclarationVariable')
    // 对象属性
    static PropertyObject = new AstType('PropertyObject')

    constructor(name) {
        this.enumName = name
    }

    toString() {
        return `${this.constructor.name}.${this.enumName}`
    }
}

const Num = (n) => {
    return {
        type: TokenType.number,
        value: n,
    }
}

const Str = (s) => {
    return {
        type: TokenType.string,
        value: s,
    }
}

const Var = (v) => {
    return {
        type: TokenType.variable,
        value: v,
    }
}

const Declaration = (name, value) => {
    return {
        type: AstType.DeclarationVariable,
        kind: 'var',
        variable: name,
        value: value,
    }
}

const Less = (left, right) => {
    return {
        type: AstType.ExpressionBinary,
        operator: {
            type: TokenType.lessThan,
            value: '<',
        },
        left: left,
        right: right,
    }
}

const Greater = (left, right) => {
    return {
        type: AstType.ExpressionBinary,
        operator: {
            type: TokenType.greaterThan,
            value: '>',
        },
        left: left,
        right: right,
    }
}

const Plus = (left, right) => {
    return {
        type: AstType.ExpressionBinary,
        operator: {
            type: TokenType.plus,
            value: '+',
        },
        left: left,
        right: right,
    }
}

const Minus = (left, right) => {
    return {
        type: AstType.ExpressionBinary,
        operator: {
            type: TokenType.minus,
            value: '-',
        },
        left: left,
        right: right,
    }
}

const Multiply = (left, right) => {
    return {
        type: AstType.ExpressionBinary,
        operator: {
            type: TokenType.multiply,
            value: '*',
        },
        left: left,
        right: right,
    }
}

const Divide = (left, right) => {
    return {
        type: AstType.ExpressionBinary,
        operator: {
            type: TokenType.divide,
            value: '/',
        },
        left: left,
        right: right,
    }
}


const If = (condition, consequent, alternate) => {
    // condition
    // consequent
    // alternate
    return {
        type: AstType.StatementIf,
        // if块运行的条件, 可以是表达式等
        condition: condition,
        consequent: consequent,
        alternate: alternate,
    }
}

const Block = (body) => {
    return {
        type: AstType.StatementBlock,
        body: body,
    }
}

const Call = (callee, arguments) => {
    return {
        type: AstType.ExpressionCall,
        callee: callee,
        arguments: arguments,
    }
}

const Return = (value) => {
    return {
        type: AstType.StatementReturn,
        value: value,
    }

}
const Fun = (params, body) => {
    return {
        type: AstType.ExpressionFunction,
        params: params,
        body: body,
    }
}
const Class = (body) => {
    return {
        type: AstType.ExpressionClass,
        body: body,
    }
}
const True = () => {
    return {
        type: TokenType.boolean,
        value: true,
    }
}

const False = () => {
    return {
        type: TokenType.boolean,
        value: false,
    }
}
const Assign = (left, right) => {
    return {
        type: AstType.ExpressionAssignment,
        left: left,
        operator: {
            type: TokenType.assign,
            value: '=',
        },
        right: right,
    }
}
const Array = (elements) => {
    return {
        type: AstType.ExpressionArray,
        elements: elements,
    }
}
//arr[0]
const ArrayAccess = (name, index) => {
    return {
        type: AstType.ExpressionArrayAccess,
        object: name,
        property: index,
    }
}

const Obj = (properties) => {
    return {
        type: AstType.ExpressionObject,
        properties: properties,
    }
}

//this.a this.add(1, 2)
const DotAccess = (name, property) => {
    return {
        type: AstType.ExpressionDotAccess,
        object: name,
        property: property,
    }
}


const While = (condition, body) => {
    return {
        type: AstType.StatementWhile,
        condition: condition,
        body: body,
    }
}

const For = (init, condition, update, body) => {
    return {
        type: AstType.StatementFor,
        // 初始化
        init: init,
        // for的循环判断
        condition: condition,
        // for的变量更新
        update: update,
        body: body,
    }
}

